var transitionEnd = 'transitionend webkitTransitionEnd';

var base = {
	init:function(){

    //FRM MODAL
    this.frmModal = $('#alertModal');
    this.contentModal = $(this.frmModal).find('.modal-dialog')[0];
    $(this.contentModal).addClass("alert");
    
    //load more event.
		this.loadMore();
    //delete handler
    this.deleteHandler();
    //global transitions boolean
    base.transitions = !$('html').hasClass('no-csstransitions');

    if($(document).height() < 768){
      $('#wrapper').css({'height':($(document).height())+'px'});
    }
    $(window).resize(function(){
        $('#wrapper').css({'height':'auto'});
        $('#wrapper').css({'height':($(document).height())+'px'});
    });

	},
  loadMore: function() {
      $('.load-more').off('click').on('click', function(e) {
          e.preventDefault();
          var $el = $(this);
          var form = $el.find('form');
          var url = form.attr('action');
          var formData = "{";

          $el.hide();
          $el.before($('<div class="loader"></div>'));

          //build JSON
          $('input', form).each(function(idx, el) {
              var inputVal = isNaN(parseInt($(el).val(), 10)) ? '"' + $(el).val() + '"' : $(el).val();
              formData += '"' + $(el).attr('name') + '": ' + inputVal + ',';
          });
          formData = formData.replace(/,([^,]*)$/, '}');

          $.ajax({
              url: url,
              dataType: 'json',
              type: 'POST',
              contentType: 'application/json',
              data: formData,
              complete: function(resp) {
                  $el.prev('.loader').remove();
                  
                  if(resp.statusText == "OK"){
                      $el.before(resp.responseText);
                      $('.frm').data('frm').init();
                  } else {
                      base.showError("There was a problem loading items. Try again.");
                  }
                  $el.remove();
              }
          });
      });
  },
  deleteHandler:function(){
    if($('.delete')[0]){
      var deleteId = 0,
          $confirm = $('#confirmDialog');

       /*delete flow*/
      $('.delete').off().on('click', function(e){
          e.preventDefault();
          //show confirm dialog
          $confirm.modal("show");
          deleteId = $(e.target).data("id");
      });

      $('.btn-ok.confirm-delete').off().on('click', function(e){
          e.preventDefault();
          $confirm.modal("hide");

          $.ajax({
              url: $($(".delete-link")[0]).val(),
              dataType: 'json',
              type: 'POST',
              contentType: 'application/json',
              data: '{"id":"'+deleteId+'"}',
              complete: function(resp) {
                  var responseText = JSON.parse(resp.responseText);
                  
                  if (responseText.responseCode === "000") {
                      base.showSuccess("Record was deleted successfully.");
                      //remove and load all items again..
                      $(".item-"+deleteId).remove();
                      $(".btn-search", this.el).trigger("click");
                  } else {
                      base.showError("There was a problem deleting item. ");
                  }
              }
          });

      });
      /*end delete flow*/
    }
  },
	/**
   * Used to subscribe to events from other ui elements.
   *
   * @param  {DOM Element} el    A DOM Element that publishes the event
   * @param  {String}   ev       The name of the event
   * @param  {Function} callback A callback function
   * @return {base} object       The base object
   */
  subscribe: function(el, ev, callback) {
      $el = !el ? $('html') : $(el);
      $el.on(ev, function(e) {
          e.stopPropagation();
          callback.apply(e, arguments);
      });
      return base;
  },
  /**
   * jQuery plugin bridge. Converts a class to a jQuery plugin.
   * @param  {String} name     The name of the plugin to attach to jQuery
   * @param  {Function} constructor A constructor function
   * @param  {String} selector The DOM selector to attach to
   * @return {void}
   */
  plugin: function(name, object, selector) {
      $.fn[name] = function(options) {
          var args = Array.prototype.slice.call(arguments, 1);
          var instance;
          var retval = this.each(function() {
              instance = $.data(this, name);
              if (typeof(options) == 'string') {
                  if (instance[options]) instance[options].apply(instance, args);
              } else {
                  instance = $.data(this, name, new object(options, this));
              }
          });
          if (instance && options === undefined) {
              return instance;
          } else {
              return retval;
          }
      };
      $.fn[name].apply($(selector));
  },
  toggleElem: function(elem) {
      if (base.transitions) {
          if (elem.hasClass('active')) {
              elem.on(transitionEnd, function() {
                  elem.off(transitionEnd).css('display', 'none');
              });
              elem.removeClass('active');
          } else {
              elem.off(transitionEnd);
              elem.css('display', 'block');
              // this is a fix for adding a transition class and display:block at the same time
              // http://code.google.com/p/chromium/issues/detail?id=121340
              setTimeout(function() {
                  elem.addClass('active');
              }, 1);
          }
      } else {
          if (elem.hasClass('active')) {
              elem.removeClass('active').fadeOut('fast');
          } else {
              elem.addClass('active').fadeIn('fast');
          }
      }
  },
  toggleElems: function(elemToShow, elemToHide) {
      if (base.transitions) {
          elemToHide.off(transitionEnd);
          elemToHide.on(transitionEnd, $.proxy(function() {
              elemToHide.off(transitionEnd).css('display', 'none');
              elemToShow.css('display', 'block');
              // this is a fix for adding a transition class and display:block at the same time
              // http://code.google.com/p/chromium/issues/detail?id=121340
              setTimeout(function() {
                  elemToShow.addClass('active');
              }, 1);
          }, this));
          elemToHide.removeClass('active');
      } else {
          elemToHide.fadeOut('slow', function() {
              elemToHide.removeClass('active');
              elemToShow.fadeIn('slow', function() {
                  elemToShow.addClass('active');
              });
          });
      }
  },
  showError: function(message, avoidHide){
        $(this.contentModal).removeClass("alert-success").addClass("alert-danger");
        $(this.contentModal).html("<strong>Error</strong>: "+ message);
        $(this.frmModal).modal("show");
        if(!avoidHide){
          this.hideModal();
        }
  },
  showAlert: function(message, avoidHide){
        $(this.contentModal).removeClass("alert-success").addClass("alert-warning");
        $(this.contentModal).html("<strong>Warning</strong>: "+ message);
        $(this.frmModal).modal("show");
        if(false){
          this.hideModal();
        }
  },
  showSuccess: function(message, avoidHide){
        $(this.contentModal).addClass("alert-success");
        $(this.contentModal).html("<strong>Success</strong>: "+ message);   
        $(this.frmModal).modal("show");
        if(false){
          this.hideModal();
        }
  },
  hideModal:function(){
    setTimeout($.proxy(function(){
      $(this.frmModal).modal("hide");
    }, this), 1000);
  }
};


/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
var initializing = false,
    fnTest = /xyz/.test(function() {
        xyz;
    }) ? /\b_super\b/ : /.*/;

// The base Class implementation (does nothing)
base.Class = function() {};

// Create a new Class that inherits from this class
base.Class.extend = function(prop) {

    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
        // Check if we're overwriting an existing function
        prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn) {
            return function() {
                var tmp = this._super;

                // Add a new ._super() method that is the same method
                // but on the super-class
                this._super = _super[name];

                // The method only need to be bound temporarily, so we
                // remove it when we're done executing
                var ret = fn.apply(this, arguments);
                this._super = tmp;

                return ret;
            };
        })(name, prop[name]) : prop[name];
    }

    // The dummy class constructor

    function Class() {
        // All construction is actually done in the init method
        if (!initializing && this.init) this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
};

/**
 * @class Module
 */
base.Module = base.Class.extend({
    /**
     * Construct the object with the options and couple it with the element.
     *
     * @param {Object} options An array of options.
     * @param {DOM Element} element A DOM element.
     */
    init: function(options, element) {
        this.el = $(element);
        this.options = $.extend({
            debug: false
        }, this.options, options, this.el.data());

        this.log('[component init]', 'options', this.options, 'el', this.el, 'data-attrs', this.el.data());
    },
    /**
     * Used to publish custom events.
     *
     * @param {String} ev    The event topic to fire
     * @param {*} [var_args] Optional arguments
     * @return {this} object The Module instance
     */
    publish: function(ev) {
        var args = Array.prototype.slice.call(arguments, 1); // remove the first argument which is the event

        $(this.el).trigger(ev, args);

        this.log('publish event', ev, 'args', args);

        return this; // chainable
    },

    /**
     * Output to the console,
     * if it exists and debugging is enabled in the sub-class.
     *
     * Accepts any number of arguments, any type.
     * @param {*} var_args
     * @return {void}
     */
    log: function() {
        if (this.options.debug && window.console && window.console.log) {
            window.console.log(arguments);
        }
    }

});

// make it safe to use console.log always
(function(a){function b(){}for(var c="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","),d;!!(d=c.pop());){a[d]=a[d]||b;}})
(function(){try{console.log();return window.console;}catch(a){return (window.console={});}}());


/* concats go here via build */
var EventBus = {
  topics: {},

  subscribe: function(topic, listener) {
    // create the topic if not yet created
    if(!this.topics[topic]) this.topics[topic] = [];

    // add the listener
    this.topics[topic].push(listener);
  },

  publish: function(topic, data) {
    // return if the topic doesn't exist, or there are no listeners
    if(!this.topics[topic] || this.topics[topic].length < 1) return;

    // send the event to all listeners
    this.topics[topic].forEach(function(listener) {
      listener(data || {});
    });
  }
};

